iT邦幫忙

2022 iThome 鐵人賽

DAY 12
1
Software Development

30天學會Golang系列 第 12

Day12 - Go的 goroutine

  • 分享至 

  • xImage
  •  

goroutine

goroutines 就是一系列的 Thread 操作,意思即一支程式同時進行好幾個小程式。使用go的時候程式會將go所要執行的項目放到背景執行,繼續進行主程式的程式碼,用下面的程式碼來舉例

func main() {
	var a [10]int
	for i := 0; i < 10; i++ {
		go func(i int) {
			for {
				a[i]++  // 寫入 a
				runtime.Gosched()  // 交出控制權,否則程式會不斷的在這 for 迴圈之中
			}
		}(i)
	}
	time.Sleep(time.Millisecond)  // 加入這行主要是因為避免程式結束太快,導致後面來不及執行
	fmt.Println(a)  // 讀取 a
}

輸出結果如下 (但每次結果不盡相同,因為每次開的 Thread 的切入時間點可能都不太一樣,因此造成這個情況,這先不用糾結):

// 第一次執行
[425 515 600 353 411 467 444 452 515 511]
// 第二次執行
[775 669 667 668 478 402 467 817 819 530]

goroutine 可能的切換點有以下幾種情況

  • I/O, select
  • channel
  • 等待鎖
  • 函數調用(有時候)
  • runtime.Gosched()
  • 以上都只是參考,不能保證切換,也不能保證在其他地方不切換

ps. 上面有些沒看過的會在後面介紹

在執行過程中,可以在終端機中透過以下指令來檢測數據訪問衝突

go run -race <file_name>

以我的例子而言是輸入

go run -race day12.go

得到的結果為

==================
WARNING: DATA RACE
Read at 0x00c00013e000 by main goroutine:
  main.main()
      /Users/luckyyuho/Documents/Golang/ithome/2022/day12/day12.go:20 +0x158

Previous write at 0x00c00013e000 by goroutine 7:
  main.main.func1()
      /Users/luckyyuho/Documents/Golang/ithome/2022/day12/day12.go:14 +0x58
  main.main.func2()
      /Users/luckyyuho/Documents/Golang/ithome/2022/day12/day12.go:17 +0x44

Goroutine 7 (running) created at:
  main.main()
      /Users/luckyyuho/Documents/Golang/ithome/2022/day12/day12.go:12 +0x6c
==================

可以看到有警告提示,那主要是因為這程式中有兩行會互相衝突,分別為寫入的 a[i]++ 與讀取的 fmt.Println(a) 因為有可能在讀取的瞬間,另一個 Thread 剛好正在寫入,因此產生這個警告,看似一個小問題,但是有時候會很嚴重,打個比方,套用參考來源1的範例,如果今天同一個銀行的網路銀行有提款功能,而有個人的帳戶有1500元,但同時在兩台電腦都登入了要提款,兩台電腦都送出了提領1000的請求會怎樣呢?會不會發現1500分別各提領1000還剩500?這樣一來就會造成資料庫的衝突,那麼我們要怎麼避免這個問題呢?讓我們繼續看下去:)

第12天報到,我的老天鵝,goroutine 看似簡單,但為了要讓資料能正常讀寫,感覺有點複雜啊...

參考來源

  1. https://ithelp.ithome.com.tw/articles/10188220
  2. https://blog.wu-boy.com/2019/11/four-tips-with-select-in-golang/
  3. https://coding.m.imooc.com/classindex.html?cid=180

代碼連結

https://github.com/luckyuho/ithome30-golang


上一篇
Day11 - Go的文檔制作
下一篇
Day13 - Go的 channel (上)
系列文
30天學會Golang31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言